import WxmpRsa from 'wxmp-rsa'
import {atob} from './base.js'

export function RSA(password) {
    var B = 16
    var G = 32768
    var X = 65535
    var K = 16
    var z = 4294967296
    var j = 65536
    var J = [
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "a",
        "b",
        "c",
        "d",
        "e",
        "f"
    ]
    var V = [
        0,
        32768,
        49152,
        57344,
        61440,
        63488,
        64512,
        65024,
        65280,
        65408,
        65472,
        65504,
        65520,
        65528,
        65532,
        65534,
        65535
    ]
    var Y = [
        0,
        1,
        3,
        7,
        15,
        31,
        63,
        127,
        255,
        511,
        1023,
        2047,
        4095,
        8191,
        16383,
        32767,
        65535
    ]

    function s(e) {
        for (var t = "", n = e.length - 1; n > -1; --n)
            t += e.charAt(n);
        return t
    }

    function W(e, t) {
        var n = new i;
        n.digits[0] = 1;
        for (var a = e, r = t;;) {
            if (0 != (1 & r.digits[0]) && (n = this.multiplyMod(n, a)),
                r = T(r, 1),
                0 == r.digits[0] && 0 == h(r))
                break;
            a = this.multiplyMod(a, a)
        }
        return n
    }

    function A(e, t) {
        var n = E(e, t);
        return this.modulo(n)
    }

    function P(e) {
        var t = S(e, this.k - 1),
            n = E(t, this.mu),
            a = S(n, this.k + 1),
            i = O(e, this.k + 1),
            r = E(a, this.modulus),
            o = O(r, this.k + 1),
            s = g(i, o);
        s.isNeg && (s = _(s, this.bkplus1));
        for (var c = k(s, this.modulus) >= 0; c;)
            s = g(s, this.modulus),
            c = k(s, this.modulus) >= 0;
        return s
    }

    function T(e, t) {
        var n = Math.floor(t / B),
            a = new i;
        y(e.digits, n, a.digits, 0, e.digits.length - n);
        for (var r = t % B, o = B - r, s = 0, c = s + 1; s < a.digits.length - 1; ++s,
            ++c)
            a.digits[s] = a.digits[s] >>> r | (a.digits[c] & Y[r]) << o;
        return a.digits[a.digits.length - 1] >>>= r,
            a.isNeg = e.isNeg,
            a
    }

    function S(e, t) {
        var n = new i;
        return y(e.digits, t, n.digits, 0, n.digits.length - t),
            n
    }

    function O(e, t) {
        var n = new i;
        return y(e.digits, 0, n.digits, 0, t),
            n
    }

    function u(e) {
        for (var t = "", n = (h(e),
                h(e)); n > -1; --n)
            t += l(e.digits[n]);
        return t
    }

    function l(e) {
        for (var t = "", n = 0; n < 4; ++n)
            t += J[15 & e],
            e >>>= 4;
        return s(t)
    }

    function b(e, t) {
        var n, a, r, o = new i;
        n = h(e),
            a = 0;
        for (var s = 0; s <= n; ++s)
            r = o.digits[s] + e.digits[s] * t + a,
            o.digits[s] = r & X,
            a = r >>> K;
        return o.digits[1 + n] = a,
            o
    }

    function g(e, t) {
        var n;
        if (e.isNeg != t.isNeg)
            t.isNeg = !t.isNeg,
            n = _(e, t),
            t.isNeg = !t.isNeg;
        else {
            n = new i;
            var a, r;
            r = 0;
            for (var o = 0; o < e.digits.length; ++o)
                a = e.digits[o] - t.digits[o] + r,
                n.digits[o] = a % j,
                n.digits[o] < 0 && (n.digits[o] += j),
                r = 0 - Number(a < 0);
            if (-1 == r) {
                r = 0;
                for (var o = 0; o < e.digits.length; ++o)
                    a = 0 - n.digits[o] + r,
                    n.digits[o] = a % j,
                    n.digits[o] < 0 && (n.digits[o] += j),
                    r = 0 - Number(a < 0);
                n.isNeg = !e.isNeg
            } else
                n.isNeg = e.isNeg
        }
        return n
    }

    function k(e, t) {
        if (e.isNeg != t.isNeg)
            return 1 - 2 * Number(e.isNeg);
        for (var n = e.digits.length - 1; n >= 0; --n)
            if (e.digits[n] != t.digits[n])
                return e.isNeg ? 1 - 2 * Number(e.digits[n] > t.digits[n]) : 1 - 2 * Number(e.digits[n] < t.digits[n]);
        return 0
    }

    function E(e, t) {
        for (var n, a, r, o = new i, s = h(e), c = h(t), l = 0; l <= c; ++l) {
            n = 0,
                r = l;
            for (var u = 0; u <= s; ++u,
                ++r)
                a = o.digits[r] + e.digits[u] * t.digits[l] + n,
                o.digits[r] = a & X,
                n = a >>> K;
            o.digits[l + s + 1] = n
        }
        return o.isNeg = e.isNeg != t.isNeg,
            o
    }

    function x(e, t) {
        var n = new i;
        return y(e.digits, 0, n.digits, t, n.digits.length - t),
            n
    }

    function Q(e, t) {
        for (var n = new Array, a = t.length, r = 0; r < a;)
            n[r] = t.charCodeAt(r),
            r++;
        for (; n.length % e.chunkSize != 0;)
            n[r++] = 0;
        var o, s, l, p = n.length,
            m = "";
        for (r = 0; r < p; r += e.chunkSize) {
            for (l = new i,
                o = 0,
                s = r; s < r + e.chunkSize; ++o)
                l.digits[o] = n[s++],
                l.digits[o] += n[s++] << 8;
            var d = e.barrett.powMod(l, e.e);
            m += (16 == e.radix ? u(d) : c(d, e.radix)) + " "
        }
        return m.substring(0, m.length - 1)
    }

    function w(e, t) {
        var n = Math.floor(t / B),
            a = new i;
        y(e.digits, 0, a.digits, n, a.digits.length - n);
        for (var r = t % B, o = B - r, s = a.digits.length - 1, c = s - 1; s > 0; --s,
            --c)
            a.digits[s] = a.digits[s] << r & X | (a.digits[c] & V[r]) >>> o;
        return a.digits[0] = a.digits[s] << r & X,
            a.isNeg = e.isNeg,
            a
    }

    function y(e, t, n, a, i) {
        for (var r = Math.min(t + i, e.length), o = t, s = a; o < r; ++o,
            ++s)
            n[s] = e[o]
    }

    function C(e, t) {
        var n, a, o = v(e),
            s = v(t),
            c = t.isNeg;
        if (o < s)
            return e.isNeg ? (n = r(F),
                    n.isNeg = !t.isNeg,
                    e.isNeg = !1,
                    t.isNeg = !1,
                    a = g(t, e),
                    e.isNeg = !0,
                    t.isNeg = c) : (n = new i,
                    a = r(e)),
                new Array(n, a);
        n = new i,
            a = e;
        for (var l = Math.ceil(s / B) - 1, u = 0; t.digits[l] < G;)
            t = w(t, 1),
            ++u,
            ++s,
            l = Math.ceil(s / B) - 1;
        a = w(a, u),
            o += u;
        for (var p = Math.ceil(o / B) - 1, m = x(t, p - l); - 1 != k(a, m);)
            ++n.digits[p - l],
            a = g(a, m);
        for (var d = p; d > l; --d) {
            var f = d >= a.digits.length ? 0 : a.digits[d],
                E = d - 1 >= a.digits.length ? 0 : a.digits[d - 1],
                y = d - 2 >= a.digits.length ? 0 : a.digits[d - 2],
                S = l >= t.digits.length ? 0 : t.digits[l],
                O = l - 1 >= t.digits.length ? 0 : t.digits[l - 1];
            n.digits[d - l - 1] = f == S ? X : Math.floor((f * j + E) / S);
            for (var C = n.digits[d - l - 1] * (S * j + O), N = f * z + (E * j + y); C > N;)
                --n.digits[d - l - 1],
                C = n.digits[d - l - 1] * (S * j | O),
                N = f * j * j + (E * j + y);
            m = x(t, d - l - 1),
                a = g(a, b(m, n.digits[d - l - 1])),
                a.isNeg && (a = _(a, m),
                    --n.digits[d - l - 1])
        }
        return a = T(a, u),
            n.isNeg = e.isNeg != c,
            e.isNeg && (n = c ? _(n, F) : g(n, F),
                t = T(t, u),
                a = g(t, a)),
            0 == a.digits[0] && 0 == h(a) && (a.isNeg = !1),
            new Array(n, a)
    }

    function v(e) {
        var B = 16
        var t, n = h(e),
            a = e.digits[n],
            i = (n + 1) * B;
        for (t = i; t > i - B && 0 == (32768 & a); --t)
            a <<= 1;
        return t
    }

    function a(e) {
        U = e,
            R = new Array(U);
        for (var t = 0; t < R.length; t++)
            R[t] = 0;
        q = new i,
            F = new i,
            F.digits[0] = 1
    }

    function i(e) {
        var R = [
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
        ]
        this.digits = "boolean" == typeof e && 1 == e ? null : R.slice(0),
            this.isNeg = !1
    }

    function p(e) {
        return e >= 48 && e <= 57 ? e - 48 : e >= 65 && e <= 90 ? 10 + e - 65 : e >= 97 && e <= 122 ? 10 + e - 97 : 0
    }

    function m(e) {
        for (var t = 0, n = Math.min(e.length, 4), a = 0; a < n; ++a)
            t <<= 4,
            t |= p(e.charCodeAt(a));
        return t
    }

    function d(e) {
        for (var t = new i, n = e.length, a = n, r = 0; a > 0; a -= 4,
            ++r)
            t.digits[r] = m(e.substr(Math.max(a - 4, 0), Math.min(a, 4)));
        return t
    }

    function h(e) {
        for (var t = e.digits.length - 1; t > 0 && 0 == e.digits[t];)
            --t;
        return t
    }

    function r(e) {
        var t = new i(!0);
        return t.digits = e.digits.slice(0),
            t.isNeg = e.isNeg,
            t
    }

    function N(e, t) {
        return C(e, t)[0]
    }

    function I(e) {
        this.modulus = r(e),
            this.k = h(this.modulus) + 1;
        var t = new i;
        t.digits[2 * this.k] = 1,
            this.mu = N(t, this.modulus),
            this.bkplus1 = new i,
            this.bkplus1.digits[this.k + 1] = 1,
            this.modulo = P,
            this.multiplyMod = A,
            this.powMod = W
    }

    function M(e, t, n) {
        this.e = d(e),
            this.d = d(t),
            this.m = d(n),
            this.chunkSize = 2 * h(this.m),
            this.radix = 16,
            this.barrett = new I(this.m)
    }
    //初始化函数
    var fun = new M('010001', '', "00b5eeb166e069920e80bebd1fea4829d3d1f3216f2aabe79b6c47a3c18dcee5fd22c2e7ac519cab59198ece036dcf289ea8201e2a0b9ded307f8fb704136eaeb670286f5ad44e691005ba9ea5af04ada5367cd724b5a26fdb5120cc95b6431604bd219c6b7d83a6f8f24b43918ea988a76f93c333aa5a20991493d4eb1117e7b1")
    //加密函数
    //输入密码
    // var password='Whxy164139';
    var clear = Q(fun, password)

    //rsa加密

    function hex2b64(h) {
        var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var b64padchar = "=";
        var i;
        var c;
        var ret = "";
        for (i = 0; i + 3 <= h.length; i += 3) {
            c = parseInt(h.substring(i, i + 3), 16);
            ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
        }
        if (i + 1 == h.length) {
            c = parseInt(h.substring(i, i + 1), 16);
            ret += b64map.charAt(c << 2);
        } else if (i + 2 == h.length) {
            c = parseInt(h.substring(i, i + 2), 16);
            ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
        }
        while ((ret.length & 3) > 0) ret += b64padchar;
        return ret;
    }


    WxmpRsa.prototype.encryptLong = function (string) {
        var k = this.getKey();
        try {
            var ct = "";
            //RSA每次加密117bytes，需要辅助方法判断字符串截取位置
            //1.获取字符串截取点
            var bytes = new Array();
            bytes.push(0);
            var byteNo = 0;
            var len, c;
            len = string.length;
            var temp = 0;
            for (var i = 0; i < len; i++) {
                c = string.charCodeAt(i);
                if (c >= 0x010000 && c <= 0x10FFFF) { //特殊字符，如Ř，Ţ
                    byteNo += 4;
                } else if (c >= 0x000800 && c <= 0x00FFFF) { //中文以及标点符号
                    byteNo += 3;
                } else if (c >= 0x000080 && c <= 0x0007FF) { //特殊字符，如È，Ò
                    byteNo += 2;
                } else { // 英文以及标点符号
                    byteNo += 1;
                }
                if ((byteNo % 117) >= 114 || (byteNo % 117) == 0) {
                    if (byteNo - temp >= 114) {
                        bytes.push(i);
                        temp = byteNo;
                    }
                }
            }
            //2.截取字符串并分段加密
            if (bytes.length > 1) {
                for (var i = 0; i < bytes.length - 1; i++) {
                    var str;
                    if (i == 0) {
                        str = string.substring(0, bytes[i + 1] + 1);
                    } else {
                        str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
                    }
                    var t1 = k.encrypt(str);
                    ct += t1;
                };
                if (bytes[bytes.length - 1] != string.length - 1) {
                    var lastStr = string.substring(bytes[bytes.length - 1] + 1);
                    ct += k.encrypt(lastStr);
                }
                return hex2b64(ct);
            }
            var t = k.encrypt(string);
            var y = hex2b64(t);
            return y;
        } catch (ex) {
            console.log(ex);
            return false;
        }
    };


    // 公钥加密
    var publickey = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYbGZLEVrbK5h1RQguir+yNiPhyaTIEz81lRNbmKq36RlaItAb+XW3NeSkPe+b8kZlzdflA2vmGGcZLALbNC4xCCNqEfqSoU4WK4xVoxQc825O7PwPjbLMxsu4+kqi8n4Oe3k0AtPvEsgkMeahORvJef25XIgQgANrYlf1jQ3q+QIDAQAB`
    var jsencrypt = new WxmpRsa();
    jsencrypt.setPublicKey(publickey);
    // 这里调用长文本的加密方法
    var ecodeMsg = jsencrypt.encryptLong(password);
    //转换base64


    // console.log(ecodeMsg)



    return {
        clear,
        ecodeMsg
    }
    // console.log('教务'+clear)}
}

export function ff_RSA(password) {
    //rsa加密

    function base64_encode(str) {
        var c1, c2, c3;
        var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var i = 0,
            len = str.length,
            string = '';

        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                string += base64EncodeChars.charAt(c1 >> 2);
                string += base64EncodeChars.charAt((c1 & 0x3) << 4);
                string += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                string += base64EncodeChars.charAt(c1 >> 2);
                string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
                string += base64EncodeChars.charAt((c2 & 0xF) << 2);
                string += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            string += base64EncodeChars.charAt(c1 >> 2);
            string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            string += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
            string += base64EncodeChars.charAt(c3 & 0x3F)
        }
        return string
    }

    function hex2b64(h) {
        var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var b64padchar = "=";
        var i;
        var c;
        var ret = "";
        for (i = 0; i + 3 <= h.length; i += 3) {
            c = parseInt(h.substring(i, i + 3), 16);
            ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
        }
        if (i + 1 == h.length) {
            c = parseInt(h.substring(i, i + 1), 16);
            ret += b64map.charAt(c << 2);
        } else if (i + 2 == h.length) {
            c = parseInt(h.substring(i, i + 2), 16);
            ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
        }
        while ((ret.length & 3) > 0) ret += b64padchar;
        return ret;
    }

    function b64tohex(base64) {

        var raw = atob(base64);

        var HEX = '';

        for (let i = 0; i < raw.length; i++) {

            var _hex = raw.charCodeAt(i).toString(16)

            HEX += (_hex.length == 2 ? _hex : '0' + _hex);
        }
        return HEX.toUpperCase();
    }



    WxmpRsa.prototype.encryptLong = function (string) {
        var k = this.getKey();
        try {
            var ct = "";
            //RSA每次加密117bytes，需要辅助方法判断字符串截取位置
            //1.获取字符串截取点
            var bytes = new Array();
            bytes.push(0);
            var byteNo = 0;
            var len, c;
            len = string.length;
            var temp = 0;
            for (var i = 0; i < len; i++) {
                c = string.charCodeAt(i);
                if (c >= 0x010000 && c <= 0x10FFFF) { //特殊字符，如Ř，Ţ
                    byteNo += 4;
                } else if (c >= 0x000800 && c <= 0x00FFFF) { //中文以及标点符号
                    byteNo += 3;
                } else if (c >= 0x000080 && c <= 0x0007FF) { //特殊字符，如È，Ò
                    byteNo += 2;
                } else { // 英文以及标点符号
                    byteNo += 1;
                }
                if ((byteNo % 117) >= 114 || (byteNo % 117) == 0) {
                    if (byteNo - temp >= 114) {
                        bytes.push(i);
                        temp = byteNo;
                    }
                }
            }
            //2.截取字符串并分段加密
            if (bytes.length > 1) {
                for (var i = 0; i < bytes.length - 1; i++) {
                    var str;
                    if (i == 0) {
                        str = string.substring(0, bytes[i + 1] + 1);
                    } else {
                        str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
                    }
                    var t1 = k.encrypt(str);
                    ct += t1;
                };
                if (bytes[bytes.length - 1] != string.length - 1) {
                    var lastStr = string.substring(bytes[bytes.length - 1] + 1);
                    ct += k.encrypt(lastStr);
                }
                return hex2b64(ct);
            }
            var t = k.encrypt(string);
            var y = hex2b64(t);
            return y;
        } catch (ex) {
            console.log(ex);
            return false;
        }
    };


    // 公钥加密
    var exponent = "AQAB";
    var modulus = `-----BEGIN PUBLIC KEY-----
    MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMsTku7s3NjWfAyvdLDR/JBqb+Hn3EIQ
    KwDvXUJhKM78YyIwsgn3sgw2iBHY+cT0pB+7BzSxKe1NjfTn2xUxjrkCAwEAAQ==
    -----END PUBLIC KEY-----`

    var jsencrypt = new WxmpRsa();
    jsencrypt.setPublicKey(modulus)

    // 这里调用长文本的加密方法
    var ecodeMsg = jsencrypt.encrypt(password)
    console.log(ecodeMsg)
    //转base64
    var encodedData = b64tohex(ecodeMsg); // 编码
    console.log(encodedData)
    return encodedData

}

export function ff_loveRSA() {

}